#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include "at_cmd.h"


static mt_msg_t  mt_msg;
static int no_usb_drv_flag;


static int open_gsm()
{
    int fd;
    struct termios options;

    fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);
    if (fd == -1) {
        perror("open_port: Unable to open /dev/ttyUSB0");
		no_usb_drv_flag = 1;
        return -1;
    }

    tcgetattr(fd, &options);
    cfsetispeed(&options, B115200);  // 设置波特率
    cfsetospeed(&options, B115200);
    options.c_cflag |= (CLOCAL | CREAD);
    tcsetattr(fd, TCSANOW, &options);

	no_usb_drv_flag = 0;
	return fd;
}

static void close_gsm(int fd)
{
	close(fd);
}


static char *send_atcmd_get_rsp( const at_cmd_t *cmd_tab)
{
	//printf("send_atcmd_get_rsp\n");
	
	int fd = open_gsm();
	if(fd<=0) {
		mt_msg.mt_flags &= ~FLAG_USB_OK;
		return NULL;
	}
	mt_msg.mt_flags |= FLAG_USB_OK;

	
	write(fd, cmd_tab->at_cmd, strlen(cmd_tab->at_cmd));  // 发送AT指令
	usleep(100000);  // 等待响应
	int res_size = 512;
	char *response = malloc(res_size);
	if(response == NULL) {
	 	goto _err_exit;
	}
	memset(response, 0, res_size);
	 
	
	 int index = 0;
	 char c;
	 int line_head_idx = -1;
	 int space_cnt = 0;
	 while(1) {
		read(fd, &c, 1);  // 逐字节读取数据
		if (c == '\n' || c=='\r') {
			if (index > 1) {
				if(response[index-1] != '\n' && response[index-1] != '\r') {
					response[index++] = '\n';
					response[index] = '\0';  // 在有效数据后添加字符串结束符
					char *out_str = response+line_head_idx;
					//printf("%s\n", out_str);  // 输出有效数据
					if(strstr(out_str, cmd_tab->rsp_ok)) {
						break;
					}
					else if(strstr(out_str, cmd_tab->rsp_err )) {
						break;
					}
					else {
						line_head_idx = -1;	// 重置索引
					}
				}
				
			}
			usleep(10000);
			
			space_cnt++;
			if(space_cnt >= 100) {
				break;
			}
			
		} 
		else if( c>= 0x02 && c<=0x7f){  //  判断是合法asc码才保存
			if(line_head_idx < 0) {
				line_head_idx = index;
			}
			response[index++] = c;	// 将有效数据存储到response数组中
			if(index >= res_size) {  // 判断接收数据是否溢出
				free(response);      //  溢出数据， 全部丢弃
				response = NULL;
				
			}
		}
		else {

			usleep(1000);    //  非法数据， 延时1ms再读
		}
	 }

_err_exit:
	 close_gsm(fd);

	 return response;

}

/*
[14:57:28.645]收←◆AT+CREG?

+CREG: 0,1

OK

□
[14:57:06.880]收←◆AT+CSQ
	
+CSQ: 28,99
	
OK




[15:20:02.092]收←◆AT+CPIN?

+CME ERROR: 10


[15:20:30.546]收←◆AT+CPIN?
	
+CPIN: READY


[15:20:34.210]收←◆AT+ICCID

+ICCID: 898604C51022D1106268

*/

const at_cmd_t at_creg = {"AT+CREG?\r\n", "OK", "+CME ERROR:", 2000};
const at_cmd_t at_csq  = {"AT+CSQ\r\n", "OK","+CME ERROR:", 2000 };
const at_cmd_t at_cpin = {"AT+CPIN?\r\n", "OK", "+CME ERROR:", 2000};
const at_cmd_t at_iccid= {"AT+ICCID\r\n", "OK","+CME ERROR:", 2000};



/*****************************************************
读取csq
return : 0~31 , csq
         -1,  read fail
***********************************************************/
int at_read_csq()
{
	//printf("at_read_csq..........\n");
	int creg = 0;
	char *out = send_atcmd_get_rsp(&at_creg);
	if(out) {
		mt_msg.mt_flags |= FLAG_MT_ON;   //  有数据回来， 就表示已开机

		// +CREG: 0,1
		int tmp1;

		char *psrc = strstr(out, "+CREG: ");	
		if(psrc) {
			psrc += 7; 
			sscanf(psrc,	"%d,%d",&tmp1, &creg);
		}

		mt_msg.creg = creg;
			
		free(out);
	}
	else {
		return -1;
	}
	//+CREG: 0,1
	
	char csq = 0;
	if(creg == 1 || creg==5) {
		out = send_atcmd_get_rsp(&at_csq);
		if(out) {
			char *psrc = strstr(out, "+CSQ: ");	
			if(psrc) {
				psrc += 6; 
				sscanf(psrc,	"%hhu",&csq);
			}
		
			free(out);
		}

	}

	mt_msg.csq = csq;
	
	return csq;
}

/************************************************************************
发送at指令透传
**************************************************************************/
int  at_raw_cmd(const char *raw_cmd)
{
	int creg = 0;
	at_cmd_t at_st ;
	char rsp_ok_str[4];
	rsp_ok_str[0] = 'O';
	rsp_ok_str[1] = 'K';
	rsp_ok_str[2] = 0;
	
	char rsp_err_str[8]; //="ERROR";
	rsp_err_str[0] = 'E';
	rsp_err_str[1] = 'R';
	rsp_err_str[2] = 'R';
	rsp_err_str[3] = 'O';
	rsp_err_str[4] = 'R';
	rsp_err_str[5] =  0;
	
		
	at_st.at_cmd = raw_cmd;
	at_st.rsp_ok = rsp_ok_str;
	at_st.rsp_err = rsp_err_str;
	at_st.timeout_ms = 2000;
	char *out = send_atcmd_get_rsp(&at_st);
	if(out) {
		printf("response:\n%s\n", out);
		free(out);
	}
	else {
		printf("at cmd no response\n");
	}

	return 0;
}


int at_detect_simcard()
{
	int sim_state = 0;
	char *out = send_atcmd_get_rsp(&at_cpin);
	if(out) {
		//+CPIN: READY
		if(strstr(out, "READY")) {
			sim_state = 1;
			
		}
		free(out);
	}
	
	if(sim_state) {
		mt_msg.mt_flags |= FLAG_SIMCARD_IN;
	}
	else {
		mt_msg.mt_flags &= ~FLAG_SIMCARD_IN;
	}

	if(sim_state) {
		out = send_atcmd_get_rsp(&at_iccid);
		if(out) {
			if(strstr(out, "OK")) {
				char *psrc = strstr(out, "+ICCID: ");
				if(psrc) {
					psrc += 8;
					strncpy(mt_msg.iccid, psrc, 20);
					mt_msg.iccid[20] = 0;
				}
			}
			free(out);
		}
	}
	
	return sim_state;

}

const mt_msg_t *get_mt_msg()
{
	return &mt_msg;
}

const mt_msg_t *read_mt_msg()
{
	if (at_detect_simcard() == 1) {
		if( at_read_csq()<0) {
			//printf("read csq err222222222\n");
			return NULL;
		}
		else {
			//printf("read csq ok\n");
		}
	}
	else {
		//printf("no simcard...\n");
	}
 	
	

	return &mt_msg;
}

int at_tst() 
{
	at_read_csq();

	at_detect_simcard();

	return 0;

#if 0

    int fd;
    struct termios options;

    fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);
    if (fd == -1) {
        perror("open_port: Unable to open /dev/ttyUSB0");
        return -1;
    }

    tcgetattr(fd, &options);
    cfsetispeed(&options, B115200);  // 设置波特率
    cfsetospeed(&options, B115200);
    options.c_cflag |= (CLOCAL | CREAD);
    tcsetattr(fd, TCSANOW, &options);

    write(fd, "AT\r\n", 4);  // 发送AT指令
    usleep(100000);  // 等待响应
    char response[100];
	int cnt = 0;
	while(1) {
	    int bytes_read = read(fd, response, sizeof(response));  // 读取响应
	    printf("read bytes=%d\n", bytes_read);
		printf("%02hhx\n", response[0]);
		printf("%02hhx\n", response[1]);
		
		cnt += bytes_read;
	    response[bytes_read] = '\0';
	    printf("%s", response);
		usleep(100000);  

		if(cnt >=200) break;
		
	}

    close(fd);
    return 0;
#endif	
}
